package com.time.workbench.efficient.handle;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
import com.jcraft.jsch.Session;
import com.time.workbench.core.exception.DeployException;
import com.time.workbench.core.util.AssertUtil;
import com.time.workbench.efficient.consts.CmdConst;
import com.time.workbench.efficient.entity.dto.ServerSessionConnect;
import com.time.workbench.efficient.entity.dto.ServerSessionInfo;
import com.time.workbench.efficient.util.DeployUtil;
import com.time.workbench.efficient.util.JschExecuteUtil;
import com.time.workbench.efficient.util.JschUtil;
import lombok.*;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;


/**
 * springboot部署
 */
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
public class SpringBootDeploy extends AbstractDeploy {


    /**
     * git拉取的本地目录
     */
    private String gitPullBaseDirectory;

    /**
     * git地址
     */
    private String gitRemoteAddress;

    /**
     * 拉取分支
     */
    private String branch;

    /**
     * 编译模块
     */
    private String packageModule = "";

    /**
     * 项目code
     */
    private String projectCode;

    /**
     * 检查次数
     */
    private final Integer monitorNumber = 30;
    /**
     * 每次间隔时长
     */
    private final Integer monitorTime = 1000;


    /**
     * 服务器连接对象(内部维护)
     */
    @Setter(AccessLevel.NONE)
    protected Session buildServerSession;


    /**
     * 程序运行pid (内部维护)
     */
    @Setter(AccessLevel.NONE)
    private String pid;

    /**
     * git源码路径 (内部维护)
     */
    @Setter(AccessLevel.NONE)
    private String gitSourceDirect;


    @Override
    @SneakyThrows
    public void init() {
        super.init();
        for (ServerSessionConnect serverSessionConnect : serverSessionConnects) {
            Session serverSession = DeployUtil.getSession(serverSessionConnect.getIp(), serverSessionConnect.getPort(), serverSessionConnect.getUserName(), serverSessionConnect.getPassword());
            ServerSessionInfo serverSessionInfo = new ServerSessionInfo();
            serverSessionInfo.setServerSession(serverSession);
            serverSessionInfo.setProjectPath(serverSessionConnect.getDeployPath() + File.separator + projectCode + File.separator);
            serverSessionInfo.setServerSessionConnect(serverSessionConnect);
            serverSessions.add(serverSessionInfo);
        }

        //远程目录不存在初始化
        for (ServerSessionInfo serverSession : serverSessions) {
            //初始化server.sh脚本
            String exec = JschUtil.exec(serverSession.getServerSession(), StrUtil.format(CmdConst.find, "/opt/server.sh"), StandardCharsets.UTF_8);
            if (StrUtil.isEmpty(exec)) {
                JschUtil.exec(serverSession.getServerSession(), StrUtil.format(CmdConst.mkdirP, "/opt"), StandardCharsets.UTF_8);

                String str = ResourceUtil.readUtf8Str("deploy/server.sh");
                JschExecuteUtil.remoteEdit(serverSession.getServerSession(), "/opt/server.sh", (item) -> {
                    String[] split = str.split("\n");
                    return CollectionUtil.newArrayList(split);
                });
            }

        }

        // 移动目录
        gitSourceDirect = gitPullBaseDirectory + File.separator + projectCode;
        if (packageModule == null) {
            packageModule = "";
        }
        // 如果是集中服务器
        if (buildConfig.getMode().equals("gather")) {
            buildServerSession = DeployUtil.getSession(buildConfig.getServerIp(), buildConfig.getPort(), buildConfig.getUsername(), buildConfig.getPassword());
            if (!buildServerSession.isConnected()) {
                buildServerSession.connect();
            }
        }
    }

    @Override
    public void connectServer() {
        super.connectServer();
        for (ServerSessionInfo serverSession : serverSessions) {
            DeployUtil.connectServer(serverSession.getServerSession());
            if (buildServerSession != null)
                DeployUtil.connectServer(buildServerSession);
        }
    }


    @Override
    public void pullCode() {
        super.pullCode();
        pullExtracted(serverSessions, buildServerSession, this.gitPullBaseDirectory, this.gitSourceDirect, buildConfig, this.projectCode, this.gitRemoteAddress, this.branch);
    }


    @Override
    public boolean packageCode() {
        super.packageCode();
        if (packageModule == null) {
            packageModule = "";
        }
        packageExtracted(serverSessions, buildServerSession, gitSourceDirect, projectCode, packageModule, "jar");

        return isExistPackName();
    }

    @Override
    public void stop(ServerSessionInfo serverSessionInfo) {
        super.stop(serverSessionInfo);

        packageFileName = DeployUtil.getPackageFile(gitSourceDirect, packageModule, serverSessionInfo.getServerSession(), "jar");
        if (StrUtil.isEmpty(packageFileName)) {
            log.info("没找到jar包");
            throw new DeployException("没找到备份的jar包");
        }
        String jarPath = projectPath + packageFileName;
        JschUtil.exec(serverSessionInfo.getServerSession(), StrUtil.format(CmdConst.serverStop, jarPath), StandardCharsets.UTF_8);
    }

    @Override
    public void backupPackage(ServerSessionInfo serverSessionInfo) {
        super.backupPackage(serverSessionInfo);

        String source = projectPath + packageFileName;
        String target = source + ".bak";
        JschUtil.exec(serverSessionInfo.getServerSession(), StrUtil.format(CmdConst.mkdirP, projectPath), StandardCharsets.UTF_8);
        JschUtil.exec(serverSessionInfo.getServerSession(), StrUtil.format(CmdConst.mvF, source, target), StandardCharsets.UTF_8);
    }

    @Override
    public void movePackage(ServerSessionInfo serverSessionInfo) {
        super.movePackage(serverSessionInfo);
        String source = gitPullBaseDirectory + File.separator + projectCode + File.separator + packageModule + File.separator + "target" + File.separator + packageFileName;
        String target = projectPath + packageFileName;
        JschUtil.exec(serverSessionInfo.getServerSession(), StrUtil.format(CmdConst.mvF, source, target), StandardCharsets.UTF_8);
    }

    @Override
    public void start(ServerSessionInfo serverSessionInfo) {
        super.start(serverSessionInfo);
        String jarPath = projectPath + packageFileName;
        String logPath = projectPath + "logs" + File.separator;
        JschUtil.exec(serverSessionInfo.getServerSession(), StrUtil.format(CmdConst.mkdirP, logPath), StandardCharsets.UTF_8);


        JschUtil.exec(serverSessionInfo.getServerSession(), StrUtil.format(CmdConst.serverStart, jarPath, logPath), StandardCharsets.UTF_8);
        pid = JschUtil.exec(serverSessionInfo.getServerSession(), StrUtil.format(CmdConst.serverGetPid, jarPath), StandardCharsets.UTF_8);
        pid = pid.replace("\n", "");
        if (StrUtil.isEmpty(this.pid) || "0".equals(this.pid))
            throw new RuntimeException("未找到pid");
    }


    @Override
    public boolean monitorStatus(ServerSessionInfo serverSessionInfo) {
        super.monitorStatus(serverSessionInfo);
        return DeployUtil.monitorPid(pid, monitorNumber, monitorTime, projectCode, serverSessionInfo.getServerSession());
    }

    @Override
    public void freed(ServerSessionInfo serverSessionInfo) {
        super.freed(serverSessionInfo);
        JschUtil.close(serverSessionInfo.getServerSession());
        JschUtil.close(buildServerSession);
    }

    @Override
    public void notice() {
        super.notice();

    }
}
